import json
from db import DataBase
import sys, os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sample

styleDark = {
        'font': 'font-size: 15px;color: rgb(255, 255, 255);',
        'bg': 'background: rgb(52, 55, 55);',
        'height': 'height: 26;'
        }
styleLight = {
        'font': 'font-size: 15px;color: rgb(0, 0, 0);',
        'bg': 'background: rgb(240, 240, 240);',
        'height': 'height: 25;'
        }
style = { 'dark': styleDark, 'light': styleLight }

ZJ_DIR = '{}/prj/ZJ/'.format(os.getenv('HOME'))

def parseInt(digits, val):
    if val == 'None':
        return None
    val = int(val)
    if abs(val) < 10**digits: return val
    else: return None

def parseStr(digits, val):
    if val == 'None': return None
    if len(val) <= digits: return val
    else: return None


class CustomModel(QStandardItemModel):
    def __init__(self, row, col, parent):
        super().__init__(row, col, parent)
        self.column_flag_list = [True] * col
        self.col = col

    def setColumnEdit(self, i, flag):
        if i >= 0 and i < self.col:
            self.column_flag_list[i] = flag

    def flags(self, index):
        if self.column_flag_list[index.column()]:
            return Qt.ItemIsEnabled|Qt.ItemIsSelectable|Qt.ItemIsEditable
        else:
            return Qt.ItemIsEnabled|Qt.ItemIsSelectable

class ListPanel(QTreeView):
    changed = pyqtSignal(str)
    def __init__(self, style=None):
        super().__init__()
        self.initUI(style)
        self.model = None
        
    def initUI(self, style):
        self.resize(300, 400)
        self.setMinimumSize(300, 0)
        self.setMaximumSize(300, 65535)
        self.setStyleSheet('QTreeView::item {{{}{}}}'.format(style['height'], style['font']))

    def mouseDoubleClickEvent(self, e):
        self.change(self.indexAt(e.pos()))

    def refresh(self, data):
        model = QStandardItemModel(0, 1, self)
        model.setHeaderData(0, Qt.Horizontal, "DataBaseTree")
        for db in data:
            r = QStandardItem(db)
            for t in data[db]:
                item = QStandardItem(t)
                item.setData(f'{db}:{t}')
                item.setEditable(False)
                r.appendRow(item)
            model.appendRow(r)
        self.setModel(model)
        self.model = model
        self.show()

    def change(self, indx):
        if self.model is None: return
        d = self.model.itemData(indx).get(257)
        if d is not None:
            self.changed.emit(d)
        else:
            self.setExpanded(indx, not self.isExpanded(indx))

class ViewPanel(QTableView):
    def __init__(self, style=None):
        super().__init__()
        self.initUI(style)
        self.initParseFunc()
        self.model = None
        self.types = []

    def initUI(self, style):
        self.setStyleSheet(style['font'])

    def initParseFunc(self):
        self.parse_funcs = {}
        self.parse_funcs['int'] = parseInt
        self.parse_funcs['char'] = parseStr

    def parse(self, strType, val):
        ret = strType.split('(')
        if ret[0].find('int') >= 0:
            name = 'int'
        elif ret[0].find('char') >= 0:
            name = 'char'
        elif ret[0].find('date') >= 0:
            return None
        else:
            print(f'strType: {strType}')
            assert False
        digits = int(ret[1].split(')')[0])
        func = self.parse_funcs.get(name)
        return func(digits, val)

    def refresh(self, data):
        cols = len(data['head'])
        rows = len(data['datas'])
        model = CustomModel(rows, cols, self)
        types = []
        lstNames = []
        for i, c in enumerate(data['head']):
            lstNames.append(c['field'])
            if c['key'] == 'PRI':
                h = QStandardItem(c['field']+' (PRI)')
                model.setColumnEdit(i, False)
            else:
                h = QStandardItem(c['field'])
                model.setColumnEdit(i, True)
            types.append(c['type'])
            h.setTextAlignment(Qt.AlignLeft)
            model.setHorizontalHeaderItem(i, h)
        print(lstNames)
        for r, row in enumerate(data['datas']):
            print(row)
            for c, val in enumerate(row):
                model.setItem(r, c, QStandardItem(str(val)))
        self.setModel(model)
        self.model = model
        self.types = types
        self.show()

    def getDatas(self):
        datas = []
        for r in range(self.model.rowCount()):
            row = []
            for c in range(self.model.columnCount()):
                row.append(self.parse(self.types[c], self.model.item(r, c).text()))
            datas.append(row)
        return datas

class Form(QWidget):
    def __init__(self, style=None):
        super().__init__()
        self.initUI(style)
        
        with open('./cfg.json', 'r') as fp:
            cfg = json.load(fp)
        self.database = DataBase(cfg['db']['host'], cfg['db']['port'], cfg['db']['user'], cfg['db']['password'])
        self.db_name, self.table_name = None, None
        self.list.refresh(self.database.getTree())
        self.list.changed.connect(self.update)
        self.btnSave.clicked.connect(self.save)
        self.btnImport.clicked.connect(self.importSample)
        self.btnClear.clicked.connect(self.clearSample)
        
    def initUI(self, style):
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.setStyleSheet(style['bg'])
        #self.setWindowFlags(Qt.FramelessWindowHint)

        self.resize(1000, 800)
        self.list = ListPanel(style)
        self.viewer = ViewPanel(style)

        self.cbSliceType = QComboBox()
        self.cbSliceType.addItem('CV')
        self.cbSliceType.addItem('BM')

        self.btnImport = QPushButton('Import')
        self.btnImport.setStyleSheet(style['font'])

        self.btnClear = QPushButton('Clear')
        self.btnClear.setStyleSheet(style['font'])

        self.btnSave = QPushButton('Save')
        self.btnSave.setStyleSheet(style['font'])

        hbox = QHBoxLayout()
        hbox.setSpacing(0)

        hbox.addWidget(self.cbSliceType)
        hbox.addWidget(self.btnImport)
        hbox.addWidget(self.btnClear)
        hbox.addStretch(1)
        hbox.addWidget(self.btnSave)

        vbox = QVBoxLayout()
        vbox.setSpacing(0)
        vbox.addWidget(self.viewer)
        vbox.addLayout(hbox)
        
        hbox = QHBoxLayout()
        hbox.setSpacing(0)
        hbox.addWidget(self.list)
        hbox.addLayout(vbox)
        self.setLayout(hbox)
        self.show()

    def parseKey(self, key):
        db_name, table_name = '', ''
        if key is not None:
            if isinstance(key, str):
                l = key.split(':')
                if len(l) == 2:
                    db_name, table_name = l[0], l[1]
        return db_name, table_name

    def update(self, key):
        print(key)
        self.db_name, self.table_name = self.parseKey(key)
        data = self.database.query(self.db_name, self.table_name)
        if data is not None:
            self.viewer.refresh(data)

    def save(self):
        self.database.update(self.db_name, self.table_name, self.viewer.getDatas())

    def importSample(self):
        sliceType = self.cbSliceType.currentText()
        sliceDir = QFileDialog.getExistingDirectory(self, "选择玻片文件夹", ZJ_DIR)
        if sliceDir != '':
            if sliceType == 'CV':
                sample.importCVSample(sliceDir)
            elif sliceType == 'BM':
                sample.importBMSample(sliceDir)

    def clearSample(self):
        sliceType = self.cbSliceType.currentText()
        sample.clearSample(sliceType)

if __name__=='__main__':
    app = QApplication(sys.argv)
    win = Form(style['dark'])
    sys.exit(app.exec_())
